# -*- coding: utf-8 -*-
# @Author: Jerry
# @Date:   2022-03-09 16:07:59
# @Last Modified by:   Jerry
# @Last Modified time: 2022-03-09 19:08:00

# **********
# OpenCV中的图像处理 » 4_10_4_直方图-4：直方图反投影
# http://www.woshicver.com

# **********
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
import os
rootpath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
datapath = os.path.join(rootpath,'data')
imgpath = lambda name: os.path.join(datapath,name)

# **********
'''OpenCV的反投影
OpenCV提供了一个内建的函数**cv.calcBackProject**()。它的参数几乎与**cv.calchist**()函数相同。
它的一个参数是直方图，也就是物体的直方图，我们必须找到它。
另外，在传递给backproject函数之前，应该对对象直方图进行归一化。
它返回概率图像。
然后我们用圆盘内核对图像进行卷积并应用阈值。'''



#roi是我们需要找到的对象或对象区域
roi = cv.imread(imgpath('messi5_roi.jpg'))
hsv = cv.cvtColor(roi,cv.COLOR_BGR2HSV)
#目标是我们搜索的图像
target = cv.imread(imgpath('messi5.jpg'))
print target.shape
hsvt = cv.cvtColor(target,cv.COLOR_BGR2HSV)
# 使用calcHist计算roi对象的直方图
# calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]]) -> hist
roihist = cv.calcHist([hsv],[0, 1], None, [180, 256], [0, 180, 0, 256] )
# 直方图归一化并利用反传算法
# normalize(src, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]]) -> dst
cv.normalize(roihist,roihist,0,255,cv.NORM_MINMAX)
# calcBackProject(images, channels, hist, ranges, scale[, dst]) -> dst
dst = cv.calcBackProject([hsvt],[0,1],roihist,[0,180,0,256],1)
# 用圆盘进行卷积, 除噪音
# getStructuringElement(shape, ksize[, anchor]) -> retval
disc = cv.getStructuringElement(cv.MORPH_ELLIPSE,(5,5))
# filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]]) -> dst
cv.filter2D(dst,-1,disc,dst)
# 应用阈值作与操作
ret,thresh = cv.threshold(dst,50,255,0)
thresh = cv.merge((thresh,thresh,thresh)) # 合并3个通道为1张图
res = cv.bitwise_and(target,thresh) # target是3通道，所以thresh也必须是3通道才能计算
res = np.vstack((target,thresh,res)) # 横向排列3张图片
cv.imwrite('res.jpg',res)
cv.imshow('res',res)
cv.waitKey(0)



# 012345-7-9




